#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   user.py
@Time    :   2024-08-09 12:29:00
@Author  :   chakcy 
@Email   :   947105045@qq.com
@description   :   User类Dao
'''

import logging

from sqlalchemy.future import select

from ..dependencies.database import getDatabaseSession
from ..models.user import User, UserPersonal
from ..models.common import Page, DaoOut
from ..models.user import AddUserIn, UpdateUserIn, UpdatePasswordIn
from ..utils import generate_unique_id, encryption

logging.basicConfig(level=logging.ERROR)

class UserDao(object):
    """
    User类Dao

    方法：
    - getUsers(page: Page): 获取用户列表
    - getUserById(userId: str): 根据用户id获取用户
    - getUserByName(userAccount: str): 根据用户账号获取用户
    - getUsersByName(userName: str, page: Page): 根据用户名模糊查询用户
    - addUser(user: AddUserIn): 新增用户
    - updateUser(userId: str, user: AddUserIn): 更新用户
    - deleteUser(userId: str): 删除用户
    - updateUserPassword(userId: str, password: UpdatePasswordIn): 更新用户密码
    - resetPassword(userId: str): 重置用户密码
    """
    @staticmethod
    async def getUsers(page: Page) -> DaoOut:
        """
        获取用户列表

        参数：
        - page: 分页参数

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据，包含两个字段：
            - total: 用户总数
            - dataList: 用户列表，如果没有数据，则为None
        """
        async with getDatabaseSession() as session:
            query = select(User, UserPersonal) \
                .join(UserPersonal, User.userAccountId == UserPersonal.userAccountId) \
                .where((User.isDelete == 0) & (UserPersonal.isDelete == 0)) \
                .offset((page.pageNum - 1)*page.pageSize) \
                .limit(page.pageSize)
            result = await session.execute(query)
            user_user_personal_list = result.fetchall()
            if len(user_user_personal_list) == 0:
                return DaoOut(result=False, 
                              message="没有数据", 
                              data={"total": 0, "dataList": None})

            return DaoOut(result=True, 
                          message="获取成功", 
                          data={"total": len(user_user_personal_list), "dataList": user_user_personal_list})
    
    @staticmethod
    async def getUserById(userId: str) -> DaoOut:
        """
        根据用户id获取用户

        参数：
        - userId: 用户id

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据，包含两个元素：
            - 用户对象，如果没有数据，则为None
            - 用户个人信息对象，如果没有数据，则为None
        """
        async with getDatabaseSession() as session:
            query = select(User, UserPersonal) \
                .join(UserPersonal, User.userAccountId == UserPersonal.userAccountId) \
                .where(User.userAccountId == userId) \
                .where((User.isDelete == 0) & (UserPersonal.isDelete == 0))
            result = await session.execute(query)
            user_user_personal = result.fetchone()
            if user_user_personal is None:
                return DaoOut(result=False, 
                              message="没有数据", 
                              data={})
            user, user_personal = user_user_personal if user_user_personal is not None else (None, None)
            return DaoOut(result=True, 
                          message="获取成功", 
                          data=(user,user_personal))
        
    @staticmethod
    async def getUserByName(userAccount: str) -> DaoOut:
        """
        根据用户账号获取用户

        参数：
        - userAccount: 用户账号

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据，包含两个元素：
            - 用户对象，如果没有数据，则为None
            - 用户个人信息对象，如果没有数据，则为None
        """
        async with getDatabaseSession() as session:
            query = select(User, UserPersonal) \
                .join(UserPersonal, User.userAccountId == UserPersonal.userAccountId) \
                .where(User.userAccount == userAccount) \
                .where((User.isDelete == 0) & (UserPersonal.isDelete == 0))
            result = await session.execute(query)
            user_user_personal = result.fetchone()
            # print(50*"*")
            # print(user_user_personal)
            if user_user_personal is None:
                return DaoOut(result=False, message="没有数据", data={})
            user, user_personal = user_user_personal if user_user_personal is not None else (None, None)
            return DaoOut(result=True, 
                          message="获取成功", 
                          data=(user,  user_personal))

        
    @staticmethod
    async def getUsersByName(userName: str, page: Page) -> DaoOut:
        """
        根据用户名模糊查询用户
        
        参数：
        - userName: 用户名
        - page: 分页参数

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据，包含两个字段：
            - total: 用户总数
            - dataList: 用户列表，如果没有数据，则为None
        """
        async with getDatabaseSession() as session:
            query = select(User, UserPersonal) \
                .join(UserPersonal, User.userAccountId == UserPersonal.userAccountId) \
                .where(UserPersonal.userName.like(f'%{userName}%')) \
                .where((User.isDelete == 0) & (UserPersonal.isDelete == 0)) \
                .offset((page.pageNum - 1)*page.pageSize) \
                .limit(page.pageSize)
            result = await session.execute(query)
            user_user_personal_list = result.fetchall()
            if len(user_user_personal_list) == 0:
                return DaoOut(result=False, 
                              message="没有数据", 
                              data={"total": 0, "dataList": None})
            return DaoOut(result=True, 
                          message="获取成功", 
                          data={"total": len(user_user_personal_list), "dataList": user_user_personal_list})
        
    @staticmethod
    async def addUser(user: AddUserIn) -> DaoOut:
        """
        新增用户
        
        参数：
        - user: 用户信息

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据, 无
        """
        if user.userPassword != user.chackPassword:
            return DaoOut(result=False, message="两次输入的密码不一致", data={})
        async with getDatabaseSession() as session:
            try:
                user_id = generate_unique_id("USER_", 1, 1)
                userModel = User(
                    userAccountId=user_id, # type: ignore
                    createId=user_id, # type: ignore
                    updateId=user_id, # type: ignore
                    userNickname=user.userNickname, # type: ignore
                    userAccount=user.userAccount, # type: ignore
                    userPassword=encryption.hash_password(user.userPassword), # type: ignore
                ) # type: ignore
                session.add(userModel)
                user_personal_id = generate_unique_id("USER_PERSONAL_", 1, 1)
                userPersonalModel = UserPersonal(
                    userPersonalId=user_personal_id,  # type: ignore
                    userAccountId=user_id, # type: ignore
                    userName=user.userName, # type: ignore
                    userIdCardNum=user.userIdCardNum, # type: ignore
                    userPhoneNumber=user.userPhoneNumber, # type: ignore
                    userEmail=user.userEmail, # type: ignore
                    userGender=user.userGender, # type: ignore
                    userAddress=user.userAddress, # type: ignore
                ) # type: ignore
                session.add(userPersonalModel)
                await session.commit()
                return DaoOut(result=True, message="新增成功", data={})
            except Exception as e:
                await session.rollback()
                logging.error(f"Error adding user: {e}")
                return DaoOut(result=False, message="新增失败", data={})

    @staticmethod
    async def updateUser(userId: str, user: UpdateUserIn) -> DaoOut:
        """
        更新用户

        参数：
        - userId: 用户id
        - user: 用户信息

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据，包含两个元素：
            - 用户对象，如果没有数据，则为None
            - 用户个人信息对象，如果没有数据，则为None
        """
        async with getDatabaseSession() as session:
            try:
                async with session.begin():
                    query = select(User).where(User.userAccountId == userId)
                    result = await session.execute(query)
                    userModel = result.scalars().first()
                    if userModel is None:
                        return DaoOut(result=False, message="用户不存在", data={})
                    if not encryption.verify_password(user.userPassword, userModel.userPassword):
                        return DaoOut(result=False, message="旧密码错误", data={})
                    userModel.userNickname = user.userNickname
                    userModel.userAccount = user.userAccount
                    # userModel.userPassword = user.userPassword
                    query = select(UserPersonal).where(UserPersonal.userAccountId == userId)
                    result = await session.execute(query)
                    userPersonalModel = result.scalars().first()
                    if userPersonalModel is None:
                        return DaoOut(result=False, message="用户个人信息不存在", data={})
                    userPersonalModel.userPhoneNumber = user.userPhoneNumber
                    userPersonalModel.userEmail = user.userEmail
                    userPersonalModel.userGender = user.userGender
                    userPersonalModel.userAddress = user.userAddress
                return DaoOut(result=True, message="更新成功", data=(userModel, userPersonalModel))
            except Exception as e:
                await session.rollback()
                logging.error(f"Error updating user: {e}")
                return DaoOut(result=False, message="更新失败", data={})
            
    @staticmethod
    async def updateUserPassword(userId: str, update_password_in: UpdatePasswordIn) -> DaoOut:
        """
        修改用户密码

        参数：
        - userId: 用户id
        - update_password_in: 密码更新信息

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据，无
        """
        async with getDatabaseSession() as session:
            try:
                query = select(User).where(User.userAccountId == userId)
                result = await session.execute(query)
                userModel = result.scalars().first()
                if userModel is None:
                    return DaoOut(result=False, message="用户不存在", data={})
                if not encryption.verify_password(update_password_in.oldPassword, userModel.userPassword):
                    return DaoOut(result=False, message="旧密码错误", data={})
                userModel.userPassword = encryption.hash_password(update_password_in.newPassword)
                await session.commit()
                return DaoOut(result=True, message="密码更新成功", data={})
            except Exception as e:
                await session.rollback()
                logging.error(f"Error updating user password: {e}")
                return DaoOut(result=False, message="密码更新失败", data={})
    
    @staticmethod
    async def resetPassword(userId: str) -> DaoOut:
        """
        重置用户密码

        参数：
        - userId: 用户id

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据，无
        """
        async with getDatabaseSession() as session:
            try:
                query = select(User).where(User.userAccountId == userId)
                result = await session.execute(query)
                userModel = result.scalars().first()
                if userModel is None:
                    return DaoOut(result=False, message="用户不存在", data={})
                userModel.userPassword = encryption.hash_password("123456")
                await session.commit()
                return DaoOut(result=True, message="密码重置成功", data={})
            except Exception as e:
                await session.rollback()
                logging.error(f"Error resetting user password: {e}")
                return DaoOut(result=False, message="密码重置失败", data={})
            
    @staticmethod
    async def updateUserAvatar(user_id: str, avatar: str) -> DaoOut:
        """
        更新用户头像

        参数：
        - user_id: 用户id
        - avatar: 头像url

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据，无
        """
        async with getDatabaseSession() as session:
            try:
                query = select(User).where(User.userAccountId == user_id)
                result = await session.execute(query)
                user = result.scalars().first()
                if user is None:
                    return DaoOut(result=False, message="用户个人信息不存在", data={})
                user.userAvatar = avatar
                await session.commit()
                return DaoOut(result=True, message="头像更新成功", data={})
            except Exception as e:
                await session.rollback()
                logging.error(f"Error updating user avatar: {e}")
                return DaoOut(result=False, message="头像更新失败", data={})

    @staticmethod
    async def deleteUser(userId: str) -> DaoOut:
        """
        删除用户

        参数：
        - userId: 用户id

        返回值：
        - DaoOut: 返回值对象，包含三个字段：
          - result: 操作结果，True表示成功，False表示失败
          - message: 提示信息
          - data: 返回数据，无
        """
        async with getDatabaseSession() as session:
            try:
                query = select(User).where(User.userAccountId == userId)
                result = await session.execute(query)
                userModel = result.scalars().first()
                if userModel is None:
                    return DaoOut(result=False, message="用户不存在", data={})
                userModel.isDelete = 1
                query = select(UserPersonal).where(UserPersonal.userAccountId == userId)
                result = await session.execute(query)
                userPersonalModel = result.scalars().first()
                if userPersonalModel is None:
                    return DaoOut(result=False, message="用户个人信息不存在", data={})
                userPersonalModel.isDelete = 1
                await session.commit()
                return DaoOut(result=True, message="删除成功", data={})
            except Exception as e:
                await session.rollback()
                logging.error(f"Error deleting user: {e}")
                return DaoOut(result=False, message="删除失败", data={})
